'use strict'

import { app,dialog, protocol, BrowserWindow,ipcMain,Tray  } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
import {spawn,execSync} from "child_process";
import { throttle } from 'lodash';
import config from "@/config/config";

const isDevelopment = process.env.NODE_ENV !== 'production'
const path = require('path')
const treekill = require('tree-kill');
const { exec } = require('child_process');
const sudo = require('sudo-prompt');
const electron = require('electron');

// Set up the log file for info level logs (info.log)
const log = require('electron-log');
log.transports.file.level = 'info';
log.transports.file.format = '{y}-{m}-{d} {h}:{i}:{s} {text}';
log.transports.file.file = app.getPath('userData') + '/info.log';

const errorLog = log.create()
errorLog.transports.file.level = 'error';
errorLog.transports.file.format = '{y}-{m}-{d} {h}:{i}:{s} {text}';
errorLog.transports.file.file = app.getPath('userData') + '/error.log';

// 监听 Node.js 进程的 uncaughtException 事件，捕获未处理的异常并记录到日志
process.on('uncaughtException', (error) => {
  errorLog.error('Uncaught Exception:', error);
});

let win;
/**远程ssh连接*/
let sshConn
let sshStream; // 正在执行的远程命令输出流
let output=''; // 保存远程命令执行结果
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: 'app', privileges: { secure: true, standard: true } }
])

const Menu = require('electron').Menu
async function createWindow() {
  // Create the browser window.
  // 隐藏菜单栏

  Menu.setApplicationMenu(null)
   win = new BrowserWindow({
    width: 800,
    height: 600,
     icon: 'ico/icon.png',
    webPreferences: {
      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
      preload: path.join(__dirname, 'preload.js')
    }
  })

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) win.webContents.openDevTools()
  } else {
    createProtocol('app')
    // Load the index.html when not in development
    win.loadURL('app://./index.html')
  }




}

app.on('before-quit', async () => {
    stopOnListenMainRemoteMsg();
  // 调用函数以杀死端口为 process.env.PORT 的进程
  log.info('process.env.PORT:', config.port);
  const pids = killProcessByPort(config.port);
  console.log('PIDs to kill:', pids);
  for (const pid of pids) {
    console.log(`Killing process with PID ${pid} on port ${config.port}...`);
    try {
      execSync(`taskkill /F /PID ${pid}`);
      console.log(`Process with PID ${pid} on port ${config.port} has been terminated.`);
    } catch (error) {
      console.error(`Error killing process with PID ${pid}:`, error);
    }
  }
});




// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})





app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS)
    } catch (e) {
      // console.error('Vue Devtools failed to install:', e.toString())
    }
  }
  // 获取正确的资源文件路径
  const exePath = getResourcePath('dmServer/start.bat');
  runExe(exePath);
})

function getResourcePath(relativePath) {
  //path.resolve(app.getAppPath(), '..')--> prod中获取的是项目根路径/resources, dev中获取的是项目根路径
  const resourcesPath = isDevelopment?path.resolve(app.getAppPath(), '..','resources'):path.resolve(app.getAppPath(), '..')
  log.info('resourcesPath:', resourcesPath);
  return path.join(resourcesPath, relativePath);
}


app.whenReady().then(() => {
  ipcMain.handle('runExecSync',async (event,cmdStr) => {
    return runExecSync(cmdStr)
  });
  ipcMain.handle('runExec', async (event, cmdStr) => {
    return runExec(cmdStr, event.sender);
  });
  ipcMain.handle('connectToRemoteHost', async (event, cmdStr,atOnce) => {
    return connectToRemoteHost(cmdStr,atOnce);
  });

  ipcMain.handle('stopOnListenMainRemoteStream',  () => {
    return stopOnListenMainRemoteStream();
  });

  ipcMain.handle('test',  () => {
    return test();
  });

  /**上传文件*/
  ipcMain.handle('openFileDialog', async () => {
    const options = {
      properties: ['openFile'],
      filters: [{ name: 'Text Files', extensions: ['mp3', 'flac', 'wav'] }]
    };

    try {
      const result = await dialog.showOpenDialog(win, options);
      log.info('openFileDialog result:', result)
      return result.filePaths[0];
    } catch (error) {
      log.error('Error during file dialog:', error);
      throw error;
    }
  });

  ipcMain.on('stopCmdExecution',stopCmdExecution)
  createWindow()
})

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === 'win32') {
    process.on('message', (data) => {
      if (data === 'graceful-exit') {
        app.quit()
      }
    })
  } else {
    process.on('SIGTERM', () => {
      app.quit()
    })
  }
}

/**同步方法*/
function runExecSync(cmd){
  // 执行命令并获取结果
  return execSync(cmd).toString();
}


/**异步方法*/
let cmdProcess; // 保存 CMD 进程的引用
let processId;
async function runExec(cmdStr) {
  let iconv=require('iconv-lite');

  return new Promise((resolve, reject) => {
    cmdProcess = spawn(cmdStr, { shell: true});
    processId=cmdProcess.pid;
    cmdProcess.stdout.on('data', throttle((data) => {
      let arr = [];
      arr.push(data);
      let decode = iconv.decode(Buffer.concat(arr), 'UTF-8');
      win.webContents.send('onListenMainCmdMsg', decode);
    }, 200)); // 每200毫秒处理一次输出数据

    cmdProcess.on('error', (error) => {
      reject(`Command execution error: ${error.message}`);
    });

    cmdProcess.on('close', (code) => {
      console.log(`Command execution completed with code ${code}`);
      cmdProcess=null;
    });
  });
}
/** 停止 CMD 执行函数*/
function stopCmdExecution() {
  if (cmdProcess) {
    treekill(cmdProcess.pid, 'SIGTERM', (err) => {
      if (err) {
        console.error('停止进程时发生错误:', err);
      } else {
        console.log('进程已终止');
      }
    });
    cmdProcess = null; // 清空 CMD 进程引用
  }
}

// const Client = require('ssh2').Client;
const Client = null;

function connectToRemoteHost(cmdStr,atOnce) {
  return new Promise((resolve, reject) => {
    if (sshConn && sshConn.end) {
      console.log('已经建立 SSH 连接');
      executeCommand(cmdStr, atOnce,resolve); // 已经建立连接，直接执行命令
    } else {
      sshConn = new Client();
      sshConn.on('ready', () => {
        console.log('SSH connection established');
        executeCommand(cmdStr,atOnce, resolve); // 连接成功后，执行命令
      }).on('error', (err) => {
        console.error(`SSH 连接错误: ${err.message}`);
        reject(err);
      }).on('end', () => {
        console.log('SSH 连接关闭');
        sshConn = null; // 连接关闭后，清空连接变量
      });
      sshConn.connect({
        host: '192.168.1.208',
        port: 22,
        username: 'webedit',
        password: '132132'
      });
    }
  });
}

function executeCommand(cmdStr,atOnce, resolve) {
  sshConn.exec(cmdStr, (err, stream) => {
    if (err) throw err;
    sshStream = stream;
    let result = ''; // 保存命令执行结果
    stream.on('close', (code, signal) => {
      console.log(`命令执行完毕，退出码: ${code}`);
      resolve(result); // 解析 Promise，将命令执行结果作为参数传递给 resolve
    }).on('data', (data) => {
      console.log(`命令输出: ${data}`);
      //是需要立即返回的命令,直接返回
      // if (atOnce){
      //   sendMsg(data.toString())
      // }
      result=data.toString();
      console.log(result)
      output+=result
    }
    ).stderr.on('data', (data) => {
      console.error(`命令错误输出: ${data}`);
    });
  });
}


// function executeCommand(cmdStr, resolve) {
//   sshConn.exec(cmdStr, (err, stream) => {
//     if (err) throw err;
//     sshStream = stream;
//     let result = ''; // 保存命令执行结果
//     stream.on('close', (code, signal) => {
//       console.log(`命令执行完毕，退出码: ${code}`);
//       resolve(result); // 解析 Promise，将命令执行结果作为参数传递给 resolve
//     }).on('data', throttle((data) => {
//       console.log(`命令输出: ${data}`);
//       result += data.toString(); // 将命令输出追加到结果中
//       win.webContents.send('onListenMainRemoteMsg', data.toString());
//     }, 200)).stderr.on('data', (data) => {
//       console.error(`命令错误输出: ${data}`);
//     });
//   });
// }


(function(){
  setInterval(()=>{
    if (output.length===0) return;
    sendMsg(output)
    output=''
  },100)
}())

function sendMsg(msg){
  win.webContents.send('onListenMainRemoteMsg', msg);
}

async function stopOnListenMainRemoteStream() {
  if (sshStream && !sshStream.destroyed) {
    sshStream.destroy();
    console.log('当前正在执行的命令已终止');
  }
}

async function stopOnListenMainRemoteMsg() {
  await stopOnListenMainRemoteStream();
  if (sshConn && sshConn.end) {
    let sshClose = await sshConn.end();
    if (sshClose !== undefined) {
      // 连接成功关闭
      console.log('SSH 连接已成功关闭');
    } else {
      // 连接关闭失败
      console.log('SSH 连接关闭失败');
    }
  } else {
    console.log('SSH 尚未建立连接');
  }
}


function runExe(path) {
  log.info("runExePath: ",path)
  // 弹出 UAC 对话框获取管理员权限
  const options = {
    name: 'MyPluginApp', // 应用程序名称，用于 UAC 对话框显示
  };
  sudo.exec(path, options, (error, stdout, stderr) => {
    if (error) {
      log.error('Error running the exe program', error);
      showCustomErrorBox('Error', 'Error running the exe program');
      return;
    }
    console.log('Exe program executed with admin privileges.');
  });
}

function killProcessByPort(port) {
  try {
    const stdout = execSync(`netstat -ano | findstr "LISTENING" | findstr ":${port}"`, { encoding: 'utf-8' });
    const lines = stdout.trim().split('\n');
    const pids = [];

    for (const line of lines) {
      const columns = line.trim().split(/\s+/);
      const pid = columns[columns.length - 1];
      if (!isNaN(pid)) {
        pids.push(pid);
      }
    }

    return pids;
  } catch (error) {
    console.error('Error finding processes:', error);
    return [];
  }
}


function test() {
  console.log('test')
  killProcessByPort(54321)
}


function showCustomErrorBox(title, message) {
  const options = {
    type: 'error',
    title: title,
    message: message,
    buttons: ['OK'],
    defaultId: 0,
    noLink: true, // 禁用默认链接样式
    normalizeAccessKeys: true, // 允许在消息中使用 '&' 符号作为快捷键
    cancelId: 0, // 设定取消按钮的索引，这里设为0，即对话框关闭时返回的值为0
  };

  dialog.showMessageBox(null, options);
}
